﻿#region Author

//// Rob Eisenberg, Blue Spire Consulting, Inc 

#endregion

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows.Input;
using Silverlight.Core.Infrastructure.Actions;

namespace Silverlight.Core.Infrastructure
{
	public class ViewModelCommand : ICommand
	{
		readonly MethodInfo _execute;
		readonly PropertyInfo _canExecute;
		readonly ViewModelBase _viewModel;

		public event EventHandler CanExecuteChanged = delegate { };

		public ViewModelCommand(ViewModelBase viewModel, MethodInfo execute, PropertyInfo canExecute)
		{
			_viewModel = viewModel;
			_execute = execute;
			_canExecute = canExecute;

			ObserveCanExecuteChanged();
		}

		void ObserveCanExecuteChanged()
		{
			if (_canExecute == null) return;

		    _viewModel.PropertyChanged += (s, e) =>
		                                      {
		                                          if (e.PropertyName != _canExecute.Name) return;
		                                          CanExecuteChanged(this, EventArgs.Empty);
		                                      };
		}

		public bool CanExecute(object parameter)
		{
			return _canExecute == null || (bool) _canExecute.GetValue(_viewModel, null);
		}

		public void Execute(object parameter)
		{
			object returnValue = _execute.Invoke(_viewModel, null);
			if (returnValue != null) HandleReturnValue(returnValue);
		}

		private static void HandleReturnValue(object returnValue)
		{
			var routine = returnValue as IEnumerable<IAction>;
			if (routine != null) Yield.Call(routine);
		}
	}
}